﻿<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title></title>
    <link href="../Resource/Css/site.css" rel="stylesheet" />
    <script src="../Resource/Jquery/jquery-1.10.2.js"></script>
    <style type="text/css">
        #thead td {
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div id="container1">
        <table id="t1" class="tab">
            <tr id="thead">
                <td tag="date" sort="desc">date</td>
                <td tag="name" sort="asc">name</td>
                <td tag="age" sort="asc">age</td>
            </tr>
            <tbody id="tbody">
            </tbody>
        </table>
    </div>
    <div id="container2"></div>
</body>
</html>
<script>
    function sortBy(arr, prop, desc, fn) {
        var props = [],
        ret = [],
        i = 0,
        len = arr.length;
        if (typeof prop == 'string') {
            for (; i < len; i++) {
                var oI = arr[i];
                (props[i] = new String(oI && oI[prop] || ''))._obj = oI;
            }
        }
        else {
            throw '参数类型错误';
        }

        if (fn != null && typeof fn == 'function') {
            props.sort(fn);
        } else {
            props.sort();
        }
        for (i = 0; i < len; i++) {
            ret[i] = props[i]._obj;
        }
        if (desc == "desc") {
            ret.reverse();
        }
        return ret;
    }
    function sortByMethod(x, y) {
        var reg = /^\d+(\.\d+)?$/;
        var result;
        var r = getDifferentItem(x["concat"](), y["concat"]());
        x = r.first;
        y = r.last;
        var res = getNumberByItem(x, y);

        x = res.first;
        y = res.last;

        if (reg.test(x) && reg.test(y)) {
            var iNum1 = parseInt(x);
            var iNum2 = parseInt(y);
            if (iNum1 < iNum2) {
                result = -1;
            } else if (iNum1 > iNum2) {
                result = 1;
            } else {
                result = 0;
            }
        }
        else if (reg.test(x) && reg.test(y) == false) {
            result = 1;
        }
        else if (reg.test(x) == false && reg.test(y)) {
            result = -1;
        }
        else {
            result = x.localeCompare(y);
        }
        return result;
    }

    function getDifferentItem(x, y) {
        var reg = /^\d+(\.\d+)?$/;
        var index = -1;
        if (x == y) {
            return { first: x, last: y };
        }
        var a1 = x.replace(/(.)(?=[^$])/g, "$1,").split(",");
        var a2 = y.replace(/(.)(?=[^$])/g, "$1,").split(",");
        var l = a1.length >= a2.length ? a1.length : a2.length;
        for (var i = 0; i < l; i++) {
            if (reg.test(a1[i]) && reg.test(a2[i])) {
                index = i;
                break;
            }
            if (a1[i] != a2[i]) {
                index = i;
                break;
            }
        }
        if (i == 0) {
            return { first: x, last: y };
        }
        else {
            var f = "";
            var l = "";
            for (var k = i; k < a1.length; k++) {
                f += a1[k];
            }
            for (var k = i; k < a2.length; k++) {
                l += a2[k];
            }
            return { first: f, last: l };
        }
    }

    function getNumberByItem(x, y) {
        var reg = /^\d+(\.\d+)?$/;
        var a1 = x.replace(/(.)(?=[^$])/g, "$1,").split(",");
        var a2 = y.replace(/(.)(?=[^$])/g, "$1,").split(",");
        var first = "";
        var last = "";
        if (reg.test(a1[0]) == false) {
            first = x;
        }
        if (reg.test(a1[0]) == false) {
            last = y;
        }
        for (var i = 0; i < a1.length; i++) {
            if (reg.test(a1[i]) && reg.test(a1[i + 1])) {
                first += a1[i];
            }
            else if (reg.test(a1[i]) && reg.test(a1[i + 1]) == false) {
                first += a1[i];
            }
            else {
                break;
            }
        }
        for (var i = 0; i < a2.length; i++) {
            if (reg.test(a2[i]) && reg.test(a2[i + 1])) {
                last += a2[i];
            }
            else if (reg.test(a2[i]) && reg.test(a2[i + 1]) == false) {
                last += a2[i];
            }
            else {
                break;
            }
        }
        return { first: first, last: last };
    }

    var sl = getDifferentItem("ab1234aaa", "ab987aab");
    var index = getNumberByItem(sl.first, sl.last);

    function sortByField(arrayToSort, sortName, sortOrder) {
        return sortBy(arrayToSort, sortName, sortOrder, sortByMethod);
    }

    var arr2 = [];
    arr2.push({ date: "2013", name: "a100bb", age: 1 });
    arr2.push({ date: "2014", name: "a2iu", age: 2 });
    arr2.push({ date: "2014", name: "a12iu", age: 2 });
    arr2.push({ date: "2013", name: "f300fff", age: 1 });
    arr2.push({ date: "2014", name: "a201fff", age: 2 });
    arr2.push({ date: "2013", name: "b", age: 3 });
    arr2.push({ date: "2013", name: "b", age: 4 });
    arr2.push({ date: "2014", name: "c", age: 5 });
    arr2.push({ date: "2015", name: "c", age: 5 });
    arr2.push({ date: "2016", name: "d", age: 5 });

    var arr3 = sortByField(arr2, "date", "asc");
    render(arr3);

    function render(arr) {
        $("#tbody tr").remove();
        var html = "";
        for (var i = 0; i < arr.length; i++) {
            html += "<tr>";
            html += "<td>" + arr[i].date + "</td>";
            html += "<td>" + arr[i].name + "</td>";
            html += "<td>" + arr[i].age + "</td>";
            html += "</tr>";
        }
        $("#tbody").append($(html));
    }

    document.getElementById("thead").addEventListener("click", function (e) {
        var name = e.target.tagName;
        if (name.toLowerCase() == "td") {
            var f = e.target.getAttribute("tag");
            var a = e.target.getAttribute("sort");

            //var g = getGroupArr(arr2, f, a);
            //var d = sortAllDataByGroup(g, f, a);

            var s = new sort(arr2, f, a);

            render(s.sortAllDataByGroup());

            if (a == "asc") {
                e.target.setAttribute("sort", "desc");
            } else {
                e.target.setAttribute("sort", "asc");
            }
        }
    }, false);

    function checkExist(arr, key) {
        if (arr.length == 0) {
            return false;
        }
        var bl = false;
        for (var i = 0; i < arr.length; i++) {
            if (arr[i] == key) {
                bl = true;
                break;
            }
        }
        return bl;
    }

    function groupArrByField(arr, field) {
        var res = [];
        var val = [];
        for (var i = 0; i < arr.length; i++) {
            if (!checkExist(res, arr[i][field])) {
                res.push(arr[i][field]);
                val.push(arr[i]);
            }
        }
        return { res: res, val: val };
    }

    function getGroupArr(arr, field, asc) {
        var res = groupArrByField(arr2, field);
        return { key: res.res, d: sortByField(res.val, field, asc) };
    }

    function sortAllDataByGroup(arr, field, asc) {
        var group = getGroupArr(arr, field, asc);
        var keys = group.key;
        var data = group.d;
        //find items which value equal keys by field.
        for (var i = 0; i < data.length; i++) {
            var items = getItemsByValue(arr2, data[i][field], field);
            var index = getIndexByValue(data, data[i][field], field);

            data.splice(index, 1, items);
        }
        data = convertData(data);
        return data;
    }

    function convertData(data) {
        var res = [];
        for (var i = 0; i < data.length; i++) {
            for (var j = 0; j < data[i].length; j++) {
                res.push(data[i][j]);
            }
        }
        return res;
    }

    function getItemsByValue(arr, value, field) {
        var res = [];
        for (var i = 0; i < arr.length; i++) {
            if (arr[i][field] == value) {
                res.push(arr[i]);
            }
        }
        return res;
    }

    function getIndexByValue(arr, value, field) {
        var index = 0;
        for (var i = 0; i < arr.length; i++) {
            if (arr[i][field] == value) {
                index = i;
            }
        }
        return index;
    }

    var sort = function (arr, field, asc) {
        this._d = arr;
        this._f = field;
        this._sortBy = asc;

        var checkExist = function (arr, key) {
            if (arr.length == 0) {
                return false;
            }
            var bl = false;
            for (var i = 0; i < arr.length; i++) {
                if (arr[i] == key) {
                    bl = true;
                    break;
                }
            }
            return bl;
        }

        var convertData = function (data) {
            var res = [];
            for (var i = 0; i < data.length; i++) {
                for (var j = 0; j < data[i].length; j++) {
                    res.push(data[i][j]);
                }
            }
            return res;
        }

        this.groupArrByField = function () {
            var res = [];
            var val = [];
            for (var i = 0; i < this._d.length; i++) {
                if (!checkExist(res, this._d[i][this._f])) {
                    res.push(this._d[i][this._f]);
                    val.push(this._d[i]);
                }
            }
            return { res: res, val: val };
        }

        this.getGroupArr = function () {
            var res = this.groupArrByField(this._d, this._f);
            return { key: res.res, d: sortByField(res.val, this._f, this._sortBy) };
        }

        this.sortAllDataByGroup = function () {
            var group = this.getGroupArr();
            var keys = group.key;
            var data = group.d;
            //find items which value equal keys by field.
            for (var i = 0; i < data.length; i++) {
                var items = this.getItemsByValue(this._d, data[i][this._f]);
                var index = this.getIndexByValue(data, data[i][this._f]);

                data.splice(index, 1, items);
            }
            data = convertData(data);
            return data;
        }

        this.getItemsByValue = function (data, value) {
            var res = [];
            for (var i = 0; i < data.length; i++) {
                if (data[i][this._f] == value) {
                    res.push(data[i]);
                }
            }
            return res;
        }

        this.getIndexByValue = function (arr, value) {
            var index = 0;
            for (var i = 0; i < arr.length; i++) {
                if (arr[i][this._f] == value) {
                    index = i;
                }
            }
            return index;
        }
    }

    //var old = { id: '1', age: 12, name: 'Damon' };
    //var newv = new Object();
    //for (var i in old) {
    //    var d = document.createElement("div");
    //    d.innerHTML = i + "---" + old[i];
    //    document.getElementById("container1").appendChild(d);

    //    newv[i] = old[i];
    //    if (i == "id") {
    //        newv[i] = 123;
    //    }
    //    else {
    //        newv[i] = old[i];
    //    }
    //}

    //for (var i in newv) {
    //    var d = document.createElement("div");
    //    d.innerHTML = i + "---" + newv[i];
    //    document.getElementById("container2").appendChild(d);
    //}
</script>
